package tech.yunland.shop.domain.service;

import com.moyuer.bsf.domain.dao.AttachmentDao;
import com.moyuer.bsf.domain.model.Attachment;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import tech.yunland.shop.domain.dao.GoodsDao;
import tech.yunland.shop.domain.dao.GoodsPackageDao;
import tech.yunland.shop.domain.dao.GoodsPackageEntryDao;
import tech.yunland.shop.domain.dao.GoodsPackagePicturesDao;
import tech.yunland.shop.domain.model.Goods;
import tech.yunland.shop.domain.model.GoodsPackage;
import tech.yunland.shop.domain.model.GoodsPackageEntry;
import tech.yunland.shop.domain.model.GoodsPackagePictures;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 促销活动服务类
 *
 * @author 王睿智<geekrize@gmail.com>
 */
@Service
public class GoodsPackageService {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private GoodsPackageDao goodsPackageDao;

    @Autowired
    private GoodsPackageEntryDao goodsPackageEntryDao;

    @Autowired
    private GoodsPackagePicturesDao goodsPackagePicturesDao;

    @Autowired
    private AttachmentDao attachmentDao;

    @Autowired
    private GoodsDao goodsDao;

    /**
     * 读取
     *
     * @param id
     * @return
     */
    public GoodsPackage get(String id) {
        return goodsPackageDao.get(id);
    }

    /**
     * 保存修改
     *
     * @param goodsPackage
     */
    public void saveOrUpdate(GoodsPackage goodsPackage) {

        if (goodsPackage.getPrice().compareTo(BigDecimal.ZERO) < 0) {

            throw new RuntimeException("实收金额不能为负数");
        }

        goodsPackageDao.saveOrUpdate(goodsPackage);

        goodsPackage.setEntries(goodsPackageEntryDao.getPackageEntry(goodsPackage));
        // 获取折扣比
        BigDecimal rate = this.getGoodsprize(goodsPackage);

        if (goodsPackage.getEntries() != null && goodsPackage.getEntries().size() > 0) {

            for (GoodsPackageEntry goodsPackageEntry : goodsPackage.getEntries()) {

                BigDecimal goodsPrice = goodsPackageEntry.getGoods().getPrice().multiply(rate);

                if (goodsPackageEntry.getGoods().getId().equals(Goods.JF_ID)) {
                    goodsPrice = BigDecimal.ZERO;
                } else if (goodsPackageEntry.getGoods().getId().equals(Goods.DJQ_ID)) {
                    goodsPackageEntry.setPrice(new BigDecimal(1).multiply(rate));
                } else {
                    goodsPackageEntry.setPrice(goodsPrice.setScale(2, BigDecimal.ROUND_HALF_UP));
                }
                goodsPackageEntryDao.saveOrUpdate(goodsPackageEntry);

            }

        }
    }

    /**
     * 计算代金券实际销售价格
     *
     * @param goodsPackage
     * @param couponQuantity
     */
    public void countCoupon(GoodsPackage goodsPackage, BigDecimal couponQuantity) {
        BigDecimal packagePrice = goodsPackage.getPrice();
        BigDecimal couponPrice = packagePrice.divide(couponQuantity, 2, BigDecimal.ROUND_HALF_UP);
        for (GoodsPackageEntry goodsPackageEntry : goodsPackage.getEntries()) {
            if (goodsPackageEntry.getGoods().getId().equals(Goods.DJQ_ID)) {
                goodsPackageEntry.setPrice(couponPrice);

            } else if (goodsPackageEntry.getGoods().getId().equals(Goods.JF_ID)) {
                goodsPackageEntry.setPrice(BigDecimal.ZERO);

            }
            goodsPackageEntryDao.saveOrUpdate(goodsPackageEntry);
        }
    }

    /**
     * 求优惠活动折扣比
     *
     * @param goodsPackage
     * @return
     */
    public BigDecimal getGoodsprize(GoodsPackage goodsPackage) {
        // 实际价格
        BigDecimal price = goodsPackage.getPrice();
        // 原始价格
        BigDecimal oldPrice = BigDecimal.ZERO;
        // 折扣比
        BigDecimal rate = BigDecimal.ZERO;

        if (goodsPackage.getEntries() != null && goodsPackage.getEntries().size() > 0) {

            // 商品原价求和
            for (GoodsPackageEntry goodsPackageEntry : goodsPackage.getEntries()) {
                // 分录商品
                Goods entryGoods = goodsPackageEntry.getGoods();
                // 区分商品类型确定原始价格合计(默认非内置原价,代金券1,积分0)
                if (entryGoods.getKindCode() != 0) {
                    oldPrice = oldPrice.add((goodsPackageEntry.getGoods().getPrice()).multiply(goodsPackageEntry.getQuantity()));
                } else if (entryGoods.getId().equals(Goods.DJQ_ID)) {
                    oldPrice = oldPrice.add(goodsPackageEntry.getQuantity());
                } else if (entryGoods.getId().equals(Goods.JF_ID)) {
                    oldPrice = oldPrice.add(BigDecimal.ZERO);
                }

                // 原始价格合计不为0的情况下获得折扣比,否则折扣比为0
                if (oldPrice.equals(BigDecimal.ZERO)) {
                    rate = BigDecimal.ZERO;
                } else {
                    rate = price.divide(oldPrice, 16, BigDecimal.ROUND_HALF_UP);
                }
                /* 判断折扣比类型 */
                // 折扣比为1
                if (new BigDecimal(1).compareTo(rate) == 0) {
                    rate = new BigDecimal(1);
                    // 折扣比为0
                } else if (rate.compareTo(BigDecimal.ZERO) == 0) {
                    rate = BigDecimal.ZERO;
                    // 折扣比大于0且不等于1
                } else if (rate.compareTo(BigDecimal.ZERO) == 1 && rate.compareTo(new BigDecimal(1)) != 0) {
                    rate = rate;
                }

            }

        }

        return rate;

    }

    /**
     * 计算商品折扣金额
     *
     * @param bill
     * @return
     */
    // public BigDecimal getGoodsPrize(GoodsPackage goodsPackage) {
    // BigDecimal amount = BigDecimal.ZERO;// 商品原始价格和
    // BigDecimal rate = BigDecimal.ZERO;// 折扣率
    // BigDecimal receivable = goodsPackage.getPrice();// 活动价格
    //
    // for (GoodsPackageEntry goodsPackageEntry : goodsPackage.getEntries()) {
    // // 如果不是内置商品，则将商品原始价格相加
    // if (goodsPackageEntry.getGoods().getKindCode() != 0) {
    // amount =
    // amount.add(goodsPackageEntry.getGoods().getPrice().multiply(goodsPackageEntry.getQuantity()));
    // // 如果是内置商品则在活动价格中减去
    // } else if (goodsPackageEntry.getGoods().getKindCode() == 0
    // && goodsPackageEntry.getGoods().getId().equals(Goods.DJQ_ID)) {
    // receivable = receivable.subtract(goodsPackageEntry.getQuantity());
    // }
    // }
    //
    // int r = receivable.compareTo(BigDecimal.ZERO);
    // int a = amount.compareTo(BigDecimal.ZERO);
    // if (r == 0) {
    // // 无折扣返回
    // rate = new BigDecimal(1);
    // } else if (r < 0) {
    // // 异常计算返回
    //
    // rate = receivable.divide(amount, 2, BigDecimal.ROUND_HALF_UP);
    //
    // /*
    // * 判断解释： 如果出现负数情况必定是因为代金券出现非1：1情况， 例如：充值100送10元另送一瓶洗发水，价值：50元
    // * 赠送金额从实际角度来讲，不应参与其他商品成本的成本核算 这种情况 应收100 - 代金券110 = -10
    // * 此时-10为代金券产生的额外成本
    // *
    // * 带入计算公式（应收（包括代金券与商品）-代金券/商品实际价格和）= 折扣率 -10/50=-0.2 此时商品计算会员价格
    // * （洗发水原始价格）50*（折扣率）-0.2=-10 也就是将代金券产生的额外成本计入洗发水中
    // *
    // * 由以上推算可得出 商品原始价格 非零 非负 代金券 非 1：1情况下是将额外成本计入打包商品中
    // */
    //
    // } else {
    // // 折扣率返回（用充值应收[不包括内置商品] 除以 商品原始价格和 得出折扣率）
    // if (a == 0) {
    // rate = new BigDecimal(1);
    // } else if (a < 0) {
    // throw new RuntimeException("单据异常：商品单价不能为负数！");
    // } else if (a > 0) {
    // rate = receivable.divide(amount, 2, BigDecimal.ROUND_HALF_UP);
    // }
    // }
    // return rate;
    // }

    /**
     * 标记删除
     *
     * @param id
     */
    public void delete(String id) {
        GoodsPackage goodsPackage = goodsPackageDao.get(id);
        if (goodsPackage.getState() != -1) {
            goodsPackage.setState(-1);
        } else {
            throw new RuntimeException("该活动已经删除");
        }
        goodsPackageDao.update(goodsPackage);
    }

    /**
     * 更新权重
     *
     * @param id
     */
    public void updateRate(String id) {
        GoodsPackage goodsPackage = goodsPackageDao.get(id);
        if (goodsPackage == null) {
            return;
        }

        if (goodsPackage.getRate().compareTo(Long.MAX_VALUE - 1) < 0) {
            goodsPackage.setRate(goodsPackage.getRate() + 1);
        }
        goodsPackageDao.update(goodsPackage);
    }

    /**
     * 读取指定分录
     *
     * @param id
     * @return
     */
    public GoodsPackageEntry getEntry(String id) {
        return goodsPackageEntryDao.get(id);
    }

    /**
     * 保存或修改分录
     *
     * @param entry
     */
    public void saveOrUpdate(GoodsPackageEntry entry) {
        goodsPackageEntryDao.saveOrUpdate(entry);
    }

    /**
     * 物理删除优惠活动分录
     *
     * @param entry
     */
    public void deleteEntry(GoodsPackageEntry entry) {
        goodsPackageEntryDao.deleteObject(entry);

        this.saveOrUpdate(entry.getOwner());


    }

    /**
     * 保存或更新优惠活动插图
     *
     * @param id
     * @param picName
     */
    public void saveOrUpdatePicture(String id, String picName) {
        String hql = "delete from GoodsPackagePictures gp where gp.goodsPackage.id=?";
        goodsPackagePicturesDao.bulkUpdate(hql, id);

        Attachment picture = new Attachment();
        picture.setFileType("image/jpeg");
        picture.setFileName(picName);
        picture.setOriginalName(picName);
        attachmentDao.save(picture);

        GoodsPackagePictures goodsPackagePictures = new GoodsPackagePictures();
        goodsPackagePictures.setGoodsPackage(goodsPackageDao.get(id));
        goodsPackagePictures.setPicture(picture);
        goodsPackagePicturesDao.save(goodsPackagePictures);
    }

    /**
     * 查找指定机构下某名称的活动
     *
     * @param name    活动名称
     * @param organId 组织ID
     * @return List<GoodsPackage>
     */
    public List<GoodsPackage> getList(String name, String organId) {
        name = StringUtils.trimToNull(name);
        organId = StringUtils.trimToNull(organId);

        if (name == null && organId == null) {
            return null;
        }

        DetachedCriteria criteria = DetachedCriteria.forClass(GoodsPackage.class);
        criteria.add(Restrictions.ne("state", -1)); // 排队标记删除的
        if (name != null) {
            criteria.add(Restrictions.eq("name", name));
        }

        if (organId != null) {
            criteria.createCriteria("organ").add(Restrictions.idEq(organId));
        }

        return goodsPackageDao.findByCriteria(criteria);
    }

    /**
     * 生成查询
     *
     * @param param    参数
     * @param states   状态集
     * @param organIds 机构集
     * @return
     */
    private DetachedCriteria genCriteria(String param, List<Integer> states, List<String> organIds) {
        param = StringUtils.trimToEmpty(param);

        DetachedCriteria criteria = DetachedCriteria.forClass(GoodsPackage.class);

        if (StringUtils.isNotBlank(param)) {
            criteria.add(Restrictions.or(Restrictions.like("code", param, MatchMode.ANYWHERE),
                    Restrictions.like("name", param, MatchMode.ANYWHERE),
                    Restrictions.like("spell", param, MatchMode.ANYWHERE),
                    Restrictions.like("remark", param, MatchMode.ANYWHERE)));
        }

        if (states != null && states.size() > 0) {
            if (states.size() == 1) {
                criteria.add(Restrictions.eq("state", states.get(0)));
            } else {
                criteria.add(Restrictions.in("state", states));
            }
        }

        if (organIds != null && organIds.size() > 0) {
            DetachedCriteria subcrit = criteria.createCriteria("organ");
            if (organIds.size() == 1) {
                subcrit.add(Restrictions.idEq(organIds.get(0)));
            } else {
                subcrit.add(Restrictions.in("id", organIds));
            }
        }


        criteria.addOrder(Order.desc("state"));
        criteria.addOrder(Order.desc("createTime"));
        criteria.addOrder(Order.desc("rate"));

        return criteria;
    }

    /**
     * 根据入参查询结果数量
     *
     * @param param    参数
     * @param states   状态集
     * @param organIds 机构集
     * @return
     */
    public int getResultSize(String param, List<Integer> states, List<String> organIds) {
        DetachedCriteria criteria = genCriteria(param, states, organIds);

        return goodsPackageDao.findByCriteria(criteria).size();
    }

    /**
     * 根据入参查询结果集
     *
     * @param param      参数
     * @param states     状态集
     * @param organIds   机构集
     * @param startIndex 起始索引
     * @param length     数量
     * @Return List<GoodsPackage>
     */
    public List<GoodsPackage> getResultInfos(String param, List<Integer> states, Integer startIndex, Integer length,
                                             List<String> organIds) {
        DetachedCriteria criteria = genCriteria(param, states, organIds);

        return goodsPackageDao.findByCriteria(criteria, startIndex, length);
    }

    /**
     * 判断分录是否存在相同商品
     *
     * @param packgeId
     * @param goodsId
     * @return List<GoodsPackageEntry>
     */
    public List<GoodsPackageEntry> findRepeatEntry(String entryId, String packgeId, String goodsId) {
        List<GoodsPackageEntry> entryList = new ArrayList<>();

        GoodsPackageEntry newGoodsPackageEntry = goodsPackageEntryDao.get(entryId);

        GoodsPackage goodsPackage = goodsPackageDao.get(packgeId);
        for (GoodsPackageEntry goodsPackageEntry : goodsPackage.getEntries()) {
            if (goodsPackageEntry.getGoods().getId().equals(goodsId) && newGoodsPackageEntry == null) {
                entryList.add(goodsPackageEntry);
            }
        }
        return entryList;
    }

    /**
     * 保存优惠活动
     *
     * @param goodsPackage
     */
    public void save(GoodsPackage goodsPackage) {
        if (goodsPackage.getPrice().compareTo(BigDecimal.ZERO) < 0) {

            throw new RuntimeException("实收金额不能为负数");
        }

        Set<GoodsPackageEntry> entries = goodsPackage.getEntries();

        Set<GoodsPackageEntry> newEntries = new HashSet<>();
        for (GoodsPackageEntry entry: entries){
            String id = entry.getGoods().getId();
            Goods goods = goodsDao.get(id);
            entry.setGoods(goods);
            newEntries.add(entry);
        }

        // 获取折扣比
        BigDecimal rate = this.getGoodsprize(goodsPackage);

        goodsPackageDao.saveOrUpdate(goodsPackage);


        for (GoodsPackageEntry goodsPackageEntry : newEntries) {

            BigDecimal goodsPrice = goodsPackageEntry.getGoods().getPrice().multiply(rate);

            if (goodsPackageEntry.getGoods().getId().equals(Goods.JF_ID)) {
                goodsPrice = BigDecimal.ZERO;
                goodsPackageEntry.setPrice(goodsPrice.multiply(rate));
            } else if (goodsPackageEntry.getGoods().getId().equals(Goods.DJQ_ID)) {
                goodsPackageEntry.setPrice(new BigDecimal(1).multiply(rate));
            } else {
                goodsPackageEntry.setPrice(goodsPrice.setScale(16, BigDecimal.ROUND_HALF_UP));
            }
            goodsPackageEntry.setOwner(goodsPackage);
            goodsPackageEntryDao.saveOrUpdate(goodsPackageEntry);

        }

    }
}
